package com.example.logic.chapter8.demo01;

import java.util.Arrays;

/**
 * @Date 2023-05-02
 * @Author Jonathan
 */
public class DynamicArray<E> {
    private static final int DEFAULT_CAPACITY = 10;
    private int size;
    private Object[] elementData;

    public DynamicArray() {
        this.elementData = new Object[DEFAULT_CAPACITY];
    }

    private void ensureCapacity(int minCapacity) {
        int oldCapacity = elementData.length;
        if (oldCapacity >= minCapacity) {
            return;
        }
        int newCapacity = oldCapacity * 2;
        if (newCapacity < minCapacity) newCapacity = minCapacity;
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    public void add(E e) {
        ensureCapacity(size + 1);
        elementData[size++] = e;
    }


    /**
     * <T extends E> 用于定义类型参数，它申明了一个类型参数T，可放在泛型类定义中类名后面、泛型方法返回值前面
     */
    public <T extends E> void addAll(DynamicArray<T> c) {
        for (int i = 0; i < c.size; i++) {
            add(c.get(i));
        }
    }

    public void addAll0(DynamicArray<E> c) {
        for (int i = 0; i < c.size; i++) {
            add(c.get(i));
        }
    }

    /**
     * 这个方法没有定义类型参数，c的类型是DynamicArray<? extends E>,
     * ？表示通配符，<? extends E>表示有限定通配符，匹配E或E的某个子类型，
     * 具体什么子类型是未知的。
     * </p>
     * <? extends E>用于实例化类型参数，它用于实例化泛型变量中的类型参数，
     * 只是这个具体类型是未知的，只知道它是E或者E的子类型
     */
    public void addAll1(DynamicArray<? extends E> c) {
        for (int i = 0; i < c.size; i++) {
            add(c.get(i));
        }
    }

    public E get(int index) {
        return (E) elementData[index];
    }

    public int size() {
        return size;
    }

    public E set(int index, E element) {
        E oldValue = get(index);
        elementData[index] = element;
        return oldValue;
    }

    public static <T> int indexOf(T[] arr, T elm) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i].equals(elm)) {
                return i;
            }
        }
        return -1;
    }


    public static int indexOf(DynamicArray<?> arr, Object elm) {
        for (int i = 0; i < arr.size; i++) {
            if (arr.get(i).equals(elm)) {
                return i;
            }
        }
        return -1;
    }

    public static <T> int indexOf0(DynamicArray<T> arr, Object elm) {
        for (int i = 0; i < arr.size; i++) {
            if (arr.get(i).equals(elm)) {
                return i;
            }
        }
        return -1;
    }


    /**
     * <T extends Comparable<T>> 称为递归类型限制
     * T表示一种数据类型，必须实现Comparable接口，
     * 且必须可以与相同类型的元素进行比较。
     */
    public static <T extends Comparable<T>> T max(T[] arr) {
        T max = arr[0];
        for (T t : arr) {
            if (t.compareTo(max) > 0) {
                max = t;
            }
        }
        return max;
    }

    /**
     * 通配符有一个限制：只能读，不能写。如果能写就违背了java关于类型安全的承诺
     */
    public static void swap(DynamicArray<?> arr, int i, int j) {
        Object tmp = arr.get(i);
        // 下面两行是错误的
//        arr.set(i, arr.get(j));
//        arr.set(j, tmp);
        swapInternal(arr, i, j);
    }

    public static <T> void swapInternal(DynamicArray<T> arr, int i, int j) {
        T tmp = arr.get(i);
        arr.set(i, arr.get(j));
        arr.set(j, tmp);
    }


    public static <D, S extends D> void copy(DynamicArray<D> dest, DynamicArray<S> src) {
        for (int i = 0; i < src.size; i++) {
            dest.add(src.get(i));
        }
    }

    public static <D> void copy0(DynamicArray<D> dest, DynamicArray<? extends D> src) {
        for (int i = 0; i < src.size; i++) {
            dest.add(src.get(i));
        }
    }

    public void copyTo(DynamicArray<E> dest) {
        for (int i = 0; i < size; i++) {
            dest.add(get(i));
        }
    }

    public void copyTo0(DynamicArray<? super E> dest) {
        for (int i = 0; i < size; i++) {
            dest.add(get(i));
        }
    }
}
